package com.xtourms.server;

import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONArray;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.xtourms.client.rm.hotel.HotelManagerService;
import com.xtourms.server.db.City;
import com.xtourms.server.db.Hotel;
import com.xtourms.server.db.Room;
import com.xtourms.server.db.Worker;
import com.xtourms.server.db.core.DBOper;
import com.xtourms.shared.field.HotelField;

@SuppressWarnings("serial")
public class HotelManagerServiceImpl extends RemoteServiceServlet implements
		HotelManagerService {

	@Override
	public String cOrMHotel(String hotelInfo) {
		String ret = null;
		Session session = DBOper.openSession();
		Transaction t = session.beginTransaction();
		try {
			t.begin();
			
			Hotel hotel = null;
			JSONObject hotelObj = new JSONObject(hotelInfo);
			int hId = hotelObj.optInt(HotelField.HOTEL_ID);
			if (0 != hId) {
				hotel = (Hotel)session.load(Hotel.class, Integer.valueOf(hId));
			}else{
				hotel = new Hotel();
			}
			
			fillTHotel(hotel, hotelObj);
			
			session.save(hotel);
			t.commit();
			ret = toJSONHotel(hotel, session).toString();
			session.close();
		} catch (JSONException e) {
			t.rollback();
		}
		return ret;
	}

	@Override
	public String cOrMRoom(String roomInfo) {
		String ret = null;
		Session session = DBOper.openSession();
		Transaction t = session.beginTransaction();
		try {
			t.begin();
			
			Room room = null;
			JSONObject roomObj = new JSONObject(roomInfo);
			int hId = roomObj.optInt(HotelField.ROOM_ID);
			if (0 != hId) {
				room = (Room)session.load(Room.class, Integer.valueOf(hId));
			}else{
				room = new Room();
			}
			
			fillTroom(room, roomObj, session);
			
			session.save(room);
			t.commit();
			ret = toJSONRoom(room).toString();
			session.close();
		} catch (JSONException e) {
			t.rollback();
		}
		return ret;
	}

	@SuppressWarnings("unchecked")
	@Override
	public String queryHotel(String condition) {
		String hql = "from Hotel hotel";
		try {
			JSONObject condObj = new JSONObject(condition);
			int cityId = condObj.optInt(HotelField.CITY_ID);
			hql += " where hotel.hotelCity=" + cityId;
			String hotelName = condObj.optString(HotelField.HOTEL_NAME);
			if (!hotelName.isEmpty()) {
				hql += " and hotel.hotelName like '%" + hotelName + "%'";
			}
			String hotelLv = condObj.optString(HotelField.HOTEL_LV);
			if(!hotelLv.isEmpty() && !hotelLv.equals("不限")){
				hql += " and hotel.hotelLv='" + hotelLv + "'";
			}
			String add = condObj.optString(HotelField.HOTEL_ADD);
			if (!add.isEmpty()) {
				hql += " and hotel.hotelAdd like '%" + add + "%'";
			}
		} catch (JSONException e1) {
			e1.printStackTrace();
		}
		Session s = DBOper.openSession();
		Transaction t = s.beginTransaction();
		t.begin();
		Query query = s.createQuery(hql);
		//TODO:分页
		query.setFirstResult(0);
		query.setMaxResults(20);
		List<Hotel> hotelList = query.list();
	
		Iterator<Hotel> hotelIter = hotelList.iterator();
		JSONArray ret = new JSONArray();
		while (hotelIter.hasNext()) {
			Hotel hotel = hotelIter.next();
			try {
				JSONObject xx = toJSONHotel(hotel, s);
				ret.put(xx);
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}

		s.close();
		return ret.toString();
	}

	@SuppressWarnings("unchecked")
	@Override
	public String queryRoom(String condition) {
		String hql = "from Room room";
		try {
			JSONObject condObj = new JSONObject(condition);
			int hotelId = condObj.optInt(HotelField.HOTEL_ID);
			hql += " where room.hotel=" + hotelId;
		} catch (JSONException e1) {
		}
		Session s = DBOper.openSession();
		Transaction t = s.beginTransaction();
		t.begin();
		Query query = s.createQuery(hql);
		List<Room> roomList = query.list();
		Iterator<Room> roomIter = roomList.iterator();
		JSONArray ret = new JSONArray();
		while (roomIter.hasNext()) {
			Room room = roomIter.next();
			try {
				JSONObject roomObj = toJSONRoom(room);
				ret.put(roomObj);
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}

		s.close();
		return ret.toString();
	}
	
	private JSONObject toJSONHotel(Hotel hotel, Session s) throws JSONException {
		JSONObject ret = new JSONObject();
		ret.put(HotelField.HOTEL_ID, hotel.getHotelId());
		ret.put(HotelField.HOTEL_NAME, hotel.getHotelName());
		ret.put(HotelField.HOTEL_LV, hotel.getHotelLv());

		ret.put(HotelField.CITY_ID, hotel.getHotelCity());
		int cid = hotel.getHotelCity();
		City city = (City) s.load(City.class, Integer.valueOf(cid));
		ret.put(HotelField.HOTEL_CITY_NAME, city.getCityName());
		ret.put(HotelField.HOTEL_PROVINCE_ID, city.getProvince()
				.getProvinceId());
		ret.put(HotelField.HOTEL_PROVINCE_NAME, city.getProvince()
				.getProvinceName());

		ret.put(HotelField.HOTEL_ADD, hotel.getHotelAdd());
		ret.put(HotelField.HOTEL_FEX, hotel.getHotelFax());
		ret.put(HotelField.HOTEL_TEL, hotel.getHotelTel());
		ret.put(HotelField.HOTEL_DES, hotel.getHotelDes());
		ret.put(HotelField.HOTEL_MANAGER_NAME, hotel.getHotelManagerName());
		ret.put(HotelField.HOTEL_MANAGER_MOBILE, hotel.getHotelManagerTel());
		ret.put(HotelField.HOTEL_LINKMAN_NAME, hotel.getHotelLinkmanName());
		ret.put(HotelField.HOTEL_LINKMAN_MOBILE, hotel.getHotelLinkmanTel());
		ret.put(HotelField.HOTEL_LINKMAN_QQ, hotel.getHotelLinkmanQq());
		ret.put(HotelField.HOTEL_PAY_MODEL, hotel.getHotelPayMode());
		ret.put(HotelField.HOTEL_UNPAY_MONEY, hotel.getHotelUnpaymoney());
		ret.put(HotelField.HOTEL_UNPAY_DAY, hotel.getHotelUnpaydays());
		ret.put(HotelField.HOTEL_BANK_HOLDER, hotel.getHotelBankHolder());
		ret.put(HotelField.HOTEL_BANK_ACCOUNT, hotel.getHotelBankAccounts());
		ret.put(HotelField.HOTEL_BANK_ADD, hotel.getHotelBankAdd());
		ret.put(HotelField.HOTEL_SYMBIOSIS, hotel.getHotelSymbiosis());
		ret.put(HotelField.HOTEL_START_DATE, hotel.getHotelBeginDate()
				.toString());
		ret.put(HotelField.HOTEL_END_DATE, hotel.getHotelEndDate().toString());
		int workerId = hotel.getLastmodifyWorker();
		Worker worker = (Worker) s.load(Worker.class, Integer
				.valueOf(workerId));
		ret.put(HotelField.LASTMODIFY_WORKER_NAME, worker.getWorkerName());
		ret.put(HotelField.LASTMODIFY_TIME, hotel.getLastmodifyTime());

		return ret;
	}
	
	private void fillTHotel(Hotel hotel, JSONObject hotelObj) throws JSONException{
		String hotelName = hotelObj.getString(HotelField.HOTEL_NAME);
		hotel.setHotelName(hotelName);
		String hotelLv = hotelObj.getString(HotelField.HOTEL_LV);
		hotel.setHotelLv(hotelLv);
		int hotelCity = hotelObj.getInt(HotelField.CITY_ID);
		hotel.setHotelCity(hotelCity);
		String hotelAdd = hotelObj.getString(HotelField.HOTEL_ADD);
		hotel.setHotelAdd(hotelAdd);
		String hotelFax = hotelObj.optString(HotelField.HOTEL_FEX);
		hotel.setHotelFax(hotelFax);
		String hotelTel = hotelObj.optString(HotelField.HOTEL_TEL);
		hotel.setHotelTel(hotelTel);
		String hotelDes = hotelObj.optString(HotelField.HOTEL_DES);
		hotel.setHotelDes(hotelDes);

		String hotelManagerName = hotelObj
				.optString(HotelField.HOTEL_MANAGER_NAME);
		hotel.setHotelManagerName(hotelManagerName);
		String hotelManagerTel = hotelObj
				.optString(HotelField.HOTEL_MANAGER_MOBILE);
		hotel.setHotelManagerTel(hotelManagerTel);
		String hotelLinkmanName = hotelObj
				.optString(HotelField.HOTEL_LINKMAN_NAME);
		hotel.setHotelLinkmanName(hotelLinkmanName);
		String hotelLinkmanQq = hotelObj
				.optString(HotelField.HOTEL_LINKMAN_QQ);
		hotel.setHotelLinkmanQq(hotelLinkmanQq);
		String hotelLinkmanTel = hotelObj
				.optString(HotelField.HOTEL_LINKMAN_MOBILE);
		hotel.setHotelLinkmanTel(hotelLinkmanTel);

		String hotelPayMode = hotelObj
				.getString(HotelField.HOTEL_PAY_MODEL);
		hotel.setHotelPayMode(hotelPayMode);
		int unpaymoney = hotelObj.optInt(HotelField.HOTEL_UNPAY_MONEY);
		hotel.setHotelUnpaymoney(Integer.valueOf(unpaymoney));
		int unpaydays = hotelObj.optInt(HotelField.HOTEL_UNPAY_DAY);
		hotel.setHotelUnpaydays(Integer.valueOf(unpaydays));
		String hotelBankHolder = hotelObj
				.optString(HotelField.HOTEL_BANK_HOLDER);
		hotel.setHotelBankHolder(hotelBankHolder);
		String hotelBankAccounts = hotelObj
				.optString(HotelField.HOTEL_BANK_ACCOUNT);
		hotel.setHotelBankAccounts(hotelBankAccounts);
		String hotelBankAdd = hotelObj.optString(HotelField.HOTEL_BANK_ADD);
		hotel.setHotelBankAdd(hotelBankAdd);

		String hotelSymbiosis = hotelObj
				.getString(HotelField.HOTEL_SYMBIOSIS);
		hotel.setHotelSymbiosis(hotelSymbiosis);
		String beginDate = hotelObj.getString(HotelField.HOTEL_START_DATE);
		Date hotelBeginDate = java.sql.Date.valueOf(beginDate);
		hotel.setHotelBeginDate(hotelBeginDate);
		String endDate = hotelObj.getString(HotelField.HOTEL_END_DATE);
		Date hotelEndDate = java.sql.Date.valueOf(endDate);
		hotel.setHotelEndDate(hotelEndDate);

		int lastmodifyWorker = hotelObj
				.getInt(HotelField.LASTMODIFY_WORKER);
		hotel.setLastmodifyWorker(lastmodifyWorker);
	}
	
	private JSONObject toJSONRoom(Room room) throws JSONException{
		JSONObject roomObj = new JSONObject();
		int aPrice = room.getRoomActualPrice();
		roomObj.put(HotelField.ROOM_ACTUAL_PRICE, aPrice);
		int bPrice = room.getRoomBasePrice();
		roomObj.put(HotelField.ROOM_BASE_PRICE, bPrice);
		int sPrice = room.getRoomSellPrice();
		roomObj.put(HotelField.ROOM_SELL_PRICE, sPrice);
		String breakfast = room.getRoomBreakfast();
		roomObj.put(HotelField.ROOM_BREAKFAST, breakfast);
		String des = room.getRoomDes();
		roomObj.put(HotelField.ROOM_DES, des);
		int rId = room.getRoomId();
		roomObj.put(HotelField.ROOM_ID, rId);
		Date sDate = room.getRoomStartDate();
		roomObj.put(HotelField.ROOM_START_DATE, sDate.toString());
		Date eDate = room.getRoomEndDate();
		roomObj.put(HotelField.ROOM_END_DATE, eDate.toString());
		String style = room.getRoomStyle();
		roomObj.put(HotelField.ROOM_STYLE, style);
		
		return roomObj;
	}
	
	private void fillTroom(Room room, JSONObject roomObj, Session session) throws JSONException{
		int aPrice = roomObj.getInt(HotelField.ROOM_ACTUAL_PRICE);
		room.setRoomActualPrice(aPrice);
		int bPrice = roomObj.getInt(HotelField.ROOM_BASE_PRICE);
		room.setRoomBasePrice(bPrice);
		int sPrice = roomObj.getInt(HotelField.ROOM_SELL_PRICE);
		room.setRoomSellPrice(sPrice);
		
		String des = roomObj.optString(HotelField.ROOM_DES);
		room.setRoomDes(des);
		String breakfast = roomObj.optString(HotelField.ROOM_BREAKFAST);
		room.setRoomBreakfast(breakfast);
		String style = roomObj.optString(HotelField.ROOM_STYLE);
		room.setRoomStyle(style);
		
		String eDateStr = roomObj.optString(HotelField.ROOM_END_DATE);
		Date eDate = java.sql.Date.valueOf(eDateStr);
		room.setRoomEndDate(eDate);
		String sDateStr = roomObj.optString(HotelField.ROOM_START_DATE);
		Date sDate = java.sql.Date.valueOf(sDateStr);
		room.setRoomStartDate(sDate);
		
		int hId = roomObj.optInt(HotelField.HOTEL_ID);
		Hotel hotel = (Hotel) session.load(Hotel.class, Integer.valueOf(hId));
		room.setHotel(hotel);
	}

	@SuppressWarnings("unchecked")
	@Override
	public String queryResult(String condition) {
		JSONArray ret = new JSONArray();
		int days = 0;
		Date startDate = null;
		String hql = "from Room room";
		try {
			JSONObject condObj = new JSONObject(condition);
			int cityId = condObj.optInt(HotelField.CITY_ID);
			hql += " where room.hotel.hotelCity=" + cityId;
			String hotelName = condObj.optString(HotelField.HOTEL_NAME);
			if (!hotelName.isEmpty()) {
				hql += " and room.hotel.hotelName like '%" + hotelName + "%'";
			}
			String hotelLv = condObj.optString(HotelField.HOTEL_LV);
			if(!hotelLv.isEmpty()){
				hql += " and room.hotel.hotelLv='" + hotelLv + "'";
			}
			String add = condObj.optString(HotelField.HOTEL_ADD);
			if (!add.isEmpty()) {
				hql += " and room.hotel.hotelAdd like '%" + add + "%'";
			}
			String roomStyle = condObj.optString(HotelField.ROOM_STYLE);
			if (!roomStyle.isEmpty()) {
				hql += " and room.roomStyle = '" + roomStyle + "'";
			}
			int lPrice = condObj.optInt(HotelField.ROOM_LOW_PRICE);
			int hPrice = condObj.optInt(HotelField.ROOM_HIGH_PRICE);
			if(hPrice !=0){
				hql += " and room.roomSellPrice between "+ lPrice +" and "+hPrice; 
			}else{
				hql += " and room.roomSellPrice>="+ lPrice;
			}
			String inDate = condObj.optString(HotelField.IN_DATE);
			hql += " and '"+ inDate +"' between room.roomStartDate and room.roomEndDate";
			startDate = java.sql.Date.valueOf(inDate);
			days = condObj.getInt(HotelField.STAY_DAYS);
		} catch (JSONException e1) {
			e1.printStackTrace();
		}
		
		Session s = DBOper.openSession();
		Transaction t = s.beginTransaction();
		t.begin();
		Query query = s.createQuery(hql);
		List<Room> roomList = query.list();
		Iterator<Room> roomIter = roomList.iterator();
		while(roomIter.hasNext()){
			Room room = roomIter.next();
			JSONObject result = new JSONObject();
			String subHql = "from Room room where room.hotel=:hotel and room.roomStyle=:style and room.roomBreakfast=:breakfast and :date between room.roomStartDate and room.roomEndDate"; 
			Hotel hotel = room.getHotel();
			String style = room.getRoomStyle();
			String breakfast = room.getRoomBreakfast();
			Date checkDate = startDate;
			boolean isValidResult = true;
			JSONArray priceOfDay = new JSONArray();
			int sum = room.getRoomSellPrice();;
			JSONObject fdayPrice = new JSONObject();
			try {
				fdayPrice.put(HotelField.ROOM_SELL_PRICE, sum);
				fdayPrice.put(HotelField.IN_DATE, checkDate.toString());
			} catch (JSONException e) {
			}
			priceOfDay.put(fdayPrice);
			for(int i = 1; i < days; i++ ){
				Query subQuery = s.createQuery(subHql);
				subQuery.setParameter("hotel", hotel);
				subQuery.setParameter("style", style);
				subQuery.setParameter("breakfast", breakfast);
				checkDate = getTomorrow(checkDate);
				subQuery.setParameter("date", checkDate);
				Room checkRoom = (Room) subQuery.uniqueResult();
				if(null == checkRoom){
					isValidResult = false;
					break;
				}else{
					int sellPrice = checkRoom.getRoomSellPrice();
					sum += sellPrice;
					JSONObject dayPrice = new JSONObject();
					try {
						dayPrice.put(HotelField.ROOM_SELL_PRICE, sellPrice);
						dayPrice.put(HotelField.IN_DATE, checkDate.toString());
					} catch (JSONException e) {
					}
					priceOfDay.put(dayPrice);
				}
			}
			if(isValidResult){
				try {
					result.put(HotelField.HOTEL, toJSONHotel(room.getHotel(), s));
					result.put(HotelField.ROOM_STYLE, room.getRoomStyle());
					result.put(HotelField.ROOM_BREAKFAST, room.getRoomBreakfast());
					result.put(HotelField.ROOM_DES, room.getRoomDes());
					result.put(HotelField.PRICE_OF_DAY, priceOfDay);
					result.put(HotelField.SUM_PRICE, sum);
				} catch (JSONException e) {
				}
				ret.put(result);
			}
		}
		s.close();
		return ret.toString();
	}

	private Date getTomorrow(Date today){
		Date tomorrow = new java.sql.Date(today.getTime()+24*60*60*1000);
		return tomorrow;
	}
}
